﻿using System;
using Autofac;
using IocPerformance.Classes.Complex;
using IocPerformance.Classes.Dummy;
using IocPerformance.Classes.Generics;
using IocPerformance.Classes.Multiple;
using IocPerformance.Classes.Standard;

namespace IocPerformance.Adapters
{
    public sealed class AutofacContainerAdapter : ContainerAdapterBase
    {
        private IContainer container;

        public override string PackageName
        {
            get { return "Autofac"; }
        }

        public override bool SupportsInterception
        {
            get { return false; }
        }

        public override bool SupportGeneric
        {
            get { return true; }
        }

        public override bool SupportsMultiple
        {
            get { return true; }
        }

        public override object Resolve(Type type)
        {
            return this.container.Resolve(type);
        }

        public override TService Resolve<TService>()
        {
            return container.Resolve<TService>();
        }

        public override void Dispose()
        {
            // Allow the container and everything it references to be disposed.
            this.container = null;
        }

        public override void Prepare()
        {
            var autofac = new ContainerBuilder();

            //autofac.Register(c => new AutofacInterceptionLogger());

            RegisterDummies(autofac);
            RegisterStandard(autofac);
            RegisterComplexObject(autofac);
            RegisterOpenGeneric(autofac);
            RegisterMultiple(autofac);
            //RegisterInterceptor(autofac);

            this.container = autofac.Build();
        }

        private static void RegisterDummies(ContainerBuilder autofac)
        {
            autofac.RegisterType<DummyOne>().As<IDummyOne>();
            autofac.RegisterType<DummyTwo>().As<IDummyTwo>();
            autofac.RegisterType<DummyThree>().As<IDummyThree>();
            autofac.RegisterType<DummyFour>().As<IDummyFour>();
            autofac.RegisterType<DummyFive>().As<IDummyFive>();
            autofac.RegisterType<DummySix>().As<IDummySix>();
            autofac.RegisterType<DummySeven>().As<IDummySeven>();
            autofac.RegisterType<DummyEight>().As<IDummyEight>();
            autofac.RegisterType<DummyNine>().As<IDummyNine>();
            autofac.RegisterType<DummyTen>().As<IDummyTen>();
        }

        private static void RegisterStandard(ContainerBuilder autofac)
        {
            autofac.RegisterType<Singleton>()
                                   .As<ISingleton>()
                                   .SingleInstance();

            autofac.RegisterType<Transient>()
                                   .As<ITransient>();

            autofac.RegisterType<Combined>()
                                   .As<ICombined>();
        }

        private static void RegisterComplexObject(ContainerBuilder autofac)
        {
            autofac.RegisterType<FirstService>().As<IFirstService>().SingleInstance();
            autofac.RegisterType<SecondService>().As<ISecondService>().SingleInstance();
            autofac.RegisterType<ThirdService>().As<IThirdService>().SingleInstance();
            autofac.RegisterType<SubObjectOne>().As<ISubObjectOne>();
            autofac.RegisterType<SubObjectTwo>().As<ISubObjectTwo>();
            autofac.RegisterType<SubObjectThree>().As<ISubObjectThree>();
            autofac.RegisterType<Complex>().As<IComplex>();
        }

        private static void RegisterOpenGeneric(ContainerBuilder autofac)
        {
            autofac.RegisterGeneric(typeof(GenericExport<>)).As(typeof(IGenericInterface<>));
            autofac.RegisterGeneric(typeof(ImportGeneric<>)).As(typeof(ImportGeneric<>));
        }

        private static void RegisterMultiple(ContainerBuilder autofac)
        {
            autofac.RegisterType<SimpleAdapterOne>().As<ISimpleAdapter>();
            autofac.RegisterType<SimpleAdapterTwo>().As<ISimpleAdapter>();
            autofac.RegisterType<SimpleAdapterThree>().As<ISimpleAdapter>();
            autofac.RegisterType<SimpleAdapterFour>().As<ISimpleAdapter>();
            autofac.RegisterType<SimpleAdapterFive>().As<ISimpleAdapter>();

            autofac.RegisterType<ImportMultiple>().As<ImportMultiple>();
        }

        //private static void RegisterInterceptor(ContainerBuilder autofac)
        //{
        //    autofac.RegisterType<Calculator>()
        //                           .As<ICalculator>()
        //                           .EnableInterfaceInterceptors();
        //}
    }
}